package main

import (
	"context"
	"fmt"
	"time"
)

// 测试主协程和子协程同时优雅退出

func run1(ctx context.Context) {
	// do something
	select {
	case <-time.After(10 * time.Second):
		fmt.Println("oversleep")
	case <-ctx.Done():
		fmt.Println("error1: ", ctx.Err())
	}
}

func run2(ctx context.Context) {
	// do something
	select {
	case <-time.After(10 * time.Second):
		fmt.Println("oversleep")
	case <-ctx.Done():
		fmt.Println("error2: ", ctx.Err())
		time.Sleep(2 * time.Second)
		fmt.Println("run2 done")
	}
}

func main() {

	ctx, cancel := context.WithCancel(context.Background())

	go run1(ctx)
	go run2(ctx)
	time.Sleep(1 * time.Second)
	cancel() //主进程手动控制取消
	time.Sleep(1 * time.Second)
	fmt.Println("done")
}

// 主进程调用cancel()后，子协程监听这个事件并执行收尾工作，但需要注意的是主进程不会等待子协程的收尾工作执行完再退出，它们是异步执行的
